package it.traveldreamWeb.customer;

import it.traveldream.beans.BookingManagerInterface;
import it.traveldream.dto.HotelDTO.HotelRoomType;
import it.traveldream.dto.ReservationDTO;
import it.traveldream.exceptions.InvalidReservationException;
import it.traveldream.exceptions.ProductNotFoundException;
import it.traveldream.exceptions.ProductSoldOutException;
import it.traveldream.exceptions.ReservationNotFoundException;
import it.traveldream.utils.DefaultValidator;
import it.traveldreamWeb.shared.HotelRoom;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

@ManagedBean(name="reservationSummaryBean")
@ViewScoped
public class ReservationSummaryBean {

	private String friendMail;
	private String error;
	
	private boolean discountAvailable;
	private boolean useDiscount;
	private BigDecimal price;
	private BigDecimal normalPrice;
	private BigDecimal discountPrice;
	
	private List<HotelRoom> chosenRooms;
	
	@EJB
	private BookingManagerInterface bookingManager;
	
	@ManagedProperty(value="#{reservationBean}")
	private ReservationBean session;

	@PostConstruct
	private void init(){
		if (this.session.getLeavingDate() == null || this.session.getDuration() < 1 ||
				this.session.getSelectedHotel() == null || this.session.getSelectedMean() == null ||
				this.session.getTravellers() < 1){
			ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
			try {
				String path = context.getRequestContextPath()+context.getRequestServletPath();
				this.session.setSuccessMessage("Please, use links inside the system");
				context.redirect(path.replace("ReservationSummary.xhtml", "home.xhtml"));
			} catch (IOException e) {
				throw new RuntimeException();
			}
		} else 
			try {
				this.session.setSuccessMessage("");
				this.discountAvailable = (this.session.getCustomer().getDiscountPercentage() > 0);
				this.chosenRooms = new ArrayList<>();
				
				Map<HotelRoomType, Integer> rooms = new HashMap<>();
				for (HotelRoom h : this.session.getSelectedRooms()){
					if (h.getSelectedRooms() != null && h.getSelectedRooms() > 0){
						rooms.put(h.getType(), h.getSelectedRooms());
						this.chosenRooms.add(h);
					}
				}

				this.normalPrice = this.bookingManager.getTotalPrice(this.session.getSelectedMean(), 
						this.session.getTravellers(), this.session.getDuration(), this.session.getSelectedHotel(), rooms, 
						this.session.getSelectedExs(), false);
				if (this.discountAvailable)
					this.discountPrice = this.bookingManager.getTotalPrice(this.session.getSelectedMean(), 
							this.session.getTravellers(), this.session.getDuration(), this.session.getSelectedHotel(), rooms, 
							this.session.getSelectedExs(), true);
				this.price = this.normalPrice;
			} catch (ProductNotFoundException e) {
				this.setError("Internal error. Please start over");
			} catch (Exception e){
				this.setError("Internal error. Please start over");
			}
	}
	
	public String book(){
		this.setError("");
		try{
			ReservationDTO r = this.session.bookTravel(this.useDiscount);
			String message = "Congratulations, you booked successfully your travel to " + this.session.getSelectedMean().getLocation().getName();
			StringBuilder params = new StringBuilder();
			
			if (this.friendMail != null && this.validate(this.friendMail)){
				String link = this.bookingManager.sendInvitationLink(r, this.session.getCustomer(), this.friendMail);
				message += " and " + this.friendMail + " will receive your invitation!";
				params.append("i=");
				params.append(link);
			}
			
			if (! params.equals(""))
				params.append("&");
			params.append("m=" + message);
			return "home.xhtml?faces-redirect=true&" + params.toString();
		} catch (ReservationNotFoundException e) {
			this.setError("Invalid request. Wrong reservation?");
			return null;
		} catch (ProductNotFoundException | InvalidReservationException e) {
			this.setError("Invalid request. Wrong products?");
			return null;
		} catch (ProductSoldOutException e) {
			String message = "Sorry, your travel is not available. Please, select another";
			return "home.xhtml?faces-redirect=true&m=" + message;
		}  catch (RuntimeException e){
			this.setError("Internal error. Please try again");
			return null;
		} 
	}
	
	public List<HotelRoom> getChosenRooms(){
		return this.chosenRooms;
	}
	
	public String getFriendMail() {
		return this.friendMail;
	}

	public void setFriendMail(String friendMail) {
		this.friendMail = friendMail;
	}

	public ReservationBean getSession() {
		return this.session;
	}

	public void setSession(ReservationBean session) {
		this.session = session;
	}

	public String getError() {
		return this.error;
	}

	public void setError(String error) {
		this.error = error;
	}

	public boolean isDiscountAvailable() {
		return this.discountAvailable;
	}

	public void setDiscountAvailable(boolean discountAvailable) {
		this.discountAvailable = discountAvailable;
	}

	public boolean isUseDiscount() {
		return this.useDiscount;
	}

	public void setUseDiscount(boolean useDiscount) {
		this.useDiscount = useDiscount;
	}
	
	public BigDecimal getPrice() {
		return this.price;
	}

	public void setPrice(BigDecimal price) {
		this.price = price;
	}

	public void toggleDiscount() {
		if (this.useDiscount)
			this.price = this.discountPrice;
		else this.price = this.normalPrice;
	}


	private boolean validate(String friendMail) {
		if (friendMail != null && friendMail != "" && 
				friendMail.matches(DefaultValidator.emailPattern))
			return true;
		return false;
	}
}
